﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;
using System.Runtime.Serialization;
using System.IO;
using System.Drawing;

namespace CreativeMatrix.RemoteMedia.NetCore
{
	// Start the service and browse to http://<machine_name>:<port>/RemoteMedia/help to view the service's generated help page
	// NOTE: By default, a new instance of the service is created for each call; change the InstanceContextMode to Single if you want
	// a single instance of the service to process all calls.	
	[ServiceContract(Namespace = "")]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
	[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
	// NOTE: If the service is renamed, remember to update the global.asax.cs file
	public class RemoteMedia
	{
		// TODO: Implement the collection resource that will contain the SampleItem instances

		//[WebGet(UriTemplate = "")]
		//public List<SampleItem> GetCollection()
		//{
		//    // TODO: Replace the current implementation to return a collection of SampleItem instances
		//    return new List<SampleItem>() { new SampleItem() { Id = 1, StringValue = "Hello" } };
		//}

		//[WebInvoke(UriTemplate = "", Method = "POST")]
		//public SampleItem Create(SampleItem instance)
		//{
		//    // TODO: Add the new instance of SampleItem to the collection
		//    throw new NotImplementedException();
		//}

		//[WebGet(UriTemplate = "{id}")]
		//public SampleItem Get(string id)
		//{
		//    // TODO: Return the instance of SampleItem with the given id
		//    throw new NotImplementedException();
		//}

		//[WebInvoke(UriTemplate = "{id}", Method = "PUT")]
		//public SampleItem Update(string id, SampleItem instance)
		//{
		//    // TODO: Update the given instance of SampleItem in the collection
		//    throw new NotImplementedException();
		//}

		
		#region new added

		private NetCoreModel _model = NetCoreModel.GetIntance();

		[WebGet(UriTemplate = "Login?Username={username}&Role={Role}")]
		public LoginResult Login(string username, string Role)
		{
			int errorCode = 0;
			
			if (String.IsNullOrEmpty(username))
				errorCode = 1;
			else if (String.IsNullOrEmpty(Role) && (Role=="student" || Role=="teacher"))
				errorCode = 2;

			if (errorCode == 0)
			{
				if (Role == "student")
				{
					User user = _model.GetUser(username);
					
					if (user != null)
						_model.Users.Remove(user as Student);

					_model.Users.Add(new Student() { Name = username, Role = Role });
				}
				else if (Role == "teacher")
				{
					_model.TeacherLogin(username);
				}
			}

			return new LoginResult() { Result = errorCode == 0 ? true : false, ErrorCode = errorCode };
		}

		[WebGet(UriTemplate = "Logout?Username={username}")]
		public LoginResult Logout(string username)
		{
			int errorCode = 0;
			User user = null;

			user = username == "Teacher" ? _model.TheTeacher as User : _model.GetUser(username) as User;

			if (user == null)
				errorCode = 1;

			if (errorCode == 0)
			{
				if (username == "Teacher")
					_model.TeacherLogout();
				else
					_model.Users.Remove(user as Student);
			}

			return new LoginResult() { Result = errorCode == 0 ? true : false, ErrorCode = errorCode };
		}

		[WebGet(UriTemplate = "Users")]
		public IList<Student> GetLoginUsers()
		{
			return _model.Users;
		}

		/// <summary>
		/// Send base64 encode screenshot to server
		/// </summary>
		/// <param name="DataSource">base64 encode string</param>
		/// <returns></returns>
		//[WebGet(UriTemplate = "Screenshot/Send?DataSource={DataSource}", Method = "POST")]
		[WebInvoke(UriTemplate = "Screenshot/Send", Method = "POST")]
		public ScreenshotResult SendScreenshot(string DataSource)
		{
			bool result = true;

			if (string.IsNullOrEmpty(DataSource))
				result = false;

			if (string.IsNullOrEmpty(_model.TheTeacher.Name))
				result = false;

			if (result == true)
			{
				NetCoreModel.GetIntance().Commands.Add(new KeyValuePair<User, Command>(NetCoreModel.GetIntance().TheTeacher, new Command() { Name = "Screenshot", Parameter = DataSource }));
			}

			return new ScreenshotResult() { Result = result };
		}

		/// <summary>
		/// Send base64 encode screenshot to server
		/// </summary>
		/// <param name="DataSource">base64 encode string</param>
		/// <returns></returns>
		[WebInvoke(UriTemplate = "Screenshot/SendStream?Username={username}", Method = "POST")]
		public ScreenshotResult SendScreenshotStream(string username, System.IO.Stream stream)
		{
			bool result = true;
			string folder = System.Web.Hosting.HostingEnvironment.MapPath("/Screenshots");
			string filename = Path.GetRandomFileName() + ".png";
			string path = Path.Combine(folder, filename);
			User user = _model.GetUser(username);

			if (user != null)
			{
				// Create dir
				if (!Directory.Exists(folder))
					Directory.CreateDirectory(folder);

				using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
				{
					int length = (int)WebOperationContext.Current.IncomingRequest.ContentLength;
					byte[] content = new byte[length];
					int realLength = stream.Read(content, 0, length);
					String DataSource = System.Text.Encoding.Default.GetString(content);
					byte[] buffer = Convert.FromBase64String(DataSource);

					if (length == 0 || realLength == 0)
						result = false;

					fs.Write(buffer, 0, buffer.Length);
					fs.Flush();
				}

				if (string.IsNullOrEmpty(_model.TheTeacher.Name))
					result = false;

				if (result == true)
				{
					string param = user.Name + "#" + DateTime.Now.ToString() + "#" + "/Screenshots/" + filename;
					_model.Commands.Add(new KeyValuePair<User, Command>(NetCoreModel.GetIntance().TheTeacher, new Command() { Name = "Screenshot", Parameter = param }));
				}
			}
			else
				result = false;

			return new ScreenshotResult() { Result = result };
		}

		[WebGet(UriTemplate = "User/Status/LockScreen?Username={username}&CanOperate={can}")]
		public ControlResult LockScreen(string username, string can)
		{
			int errorCode = 0;
			bool canOperate = bool.Parse(can);

			//User user = _model.GetUser(username);
			List<Student> userList = Utility.GetUsers(username);

			// Todo: check teach login?

			if (userList.Count == 0)
				errorCode = 1;

			if (errorCode == 0)
			{
				foreach (var student in userList)
				{
					student.LockScreen = canOperate;
					_model.Commands.Add(new KeyValuePair<User, Command>(student, new Command() { Name = "LockScreen", Parameter = canOperate ? "Lock" : "Unlock" }));
				}
			}

			return new ControlResult() { Result = errorCode == 0 ? true : false, ErrorCode = errorCode };
		}

		[WebGet(UriTemplate = "User/Status/CanSendScreenshot?Username={username}&CanOperate={can}")]
		public ControlResult UserCanSendScreenshot(string username, string can)
		{
			int errorCode = 0;
			bool canOperate = bool.Parse(can);

			List<Student> userList = Utility.GetUsers(username);

			// Todo: check teach login?

			if (userList.Count == 0)
				errorCode = 1;

			if (errorCode == 0)
			{
				foreach (var student in userList)
				{
					student.AllowSendScreenshot = canOperate;
					_model.Commands.Add(new KeyValuePair<User, Command>(student, new Command() { Name = "AllowSendScreenshot", Parameter = canOperate ? "true" : "false" }));
				}
			}

			return new ControlResult() { Result = errorCode == 0 ? true : false, ErrorCode = errorCode };
		}

		[WebGet(UriTemplate = "Screenshot/Request?Username={username}")]
		public ControlResult SendLockScreen(string username)
		{
			int errorCode = 0;

			//User user = _model.GetUser(username);
			List<Student> userList = Utility.GetUsers(username);

			if (userList.Count == 0)
				errorCode = 1;

			if (errorCode == 0)
			{
				foreach (var user in userList)
					NetCoreModel.GetIntance().Commands.Add(new KeyValuePair<User, Command>(user, new Command() { Name = "SendScreenshot" }));
			}

			return new ControlResult() { Result = errorCode == 0 ? true : false, ErrorCode = errorCode };
		}

		[WebGet(UriTemplate = "Commands?Username={username}&Remove={remove}&Command={cmdName}")]
		public IList<Command> GetCommands(string username, string remove, string cmdName)
		{
			List<Command> cmdList = new List<Command>();
			User user;
			bool removeCmd = true;	// default remove the command from the list

			if (!string.IsNullOrEmpty(remove))
				bool.TryParse(remove, out removeCmd);

			if (username.ToUpper() == "TEACHER")
				user = _model.TheTeacher;
			else
				user = _model.GetUser(username);

			foreach (var item in _model.Commands)
			{
				if (item.Key.Name == username)
				{
					if (string.IsNullOrEmpty(cmdName) || (!string.IsNullOrEmpty(cmdName) && item.Value.Name == cmdName))
						cmdList.Add(item.Value);
				}
			}

			if (removeCmd)
			{
				foreach (var item in cmdList)
					_model.Commands.Remove(new KeyValuePair<User, Command>(user, item));
			}
			
			return cmdList;
		}

		[WebGet(UriTemplate = "User?Username={username}")]
		public User GetUserState(string username)
		{
			User user = _model.GetUser(username);
			return user;
		}

		#endregion
	}
}
